﻿using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using DCS.CaclulationClient;
using DCS.CalculationClient.DCS_Service;
using DCS.CalculationClient.Settings;
using DCS.CalculationClient.View;
using DCS.Extensions.WindowsForms;

namespace DCS.CalculationClient
{
    public class Model
    {
        /// <summary> Настройки клиента. </summary>
        private readonly DcsSettings settings = DcsSettings.Load("settings.xml") ?? new DcsSettings { Id = Guid.NewGuid() };

        /// <summary> Сервис DCS. </summary>
        private DcsService dcsService;
        /// <summary> Характеристики клиента. </summary>
        
        private TaskProcessor taskProcessor;
        private MainForm view;
        private ProgressForm connectingForm;
        
        private void InitializeTaskProcessor()
        {
            taskProcessor = new TaskProcessor();

            taskProcessor.LogAdded += view.AddLog;
            taskProcessor.PortionStateChanged += view.ChangePortionState;
            taskProcessor.PortionResultUpdated += UpdatePortionResult;
        }

        public void UpdatePortionResult(TaskPortionResult result)
        {
            dcsService.SetPortionResult(result, settings.Id);
        }

        public void Calculate()
        {
            //Получаем Вычислительную порцию с сервера
            var newTask = dcsService.GetTaskPortion(settings.Id);

            if (newTask == null)
            {
                view.SetStatusLabel("На сервере отсутсвуют вычислительные задания");
                Thread.Sleep(10000);
            }
            else
            {
                taskProcessor.ProcessTask(newTask);
            }
        }

        public void SetView(MainForm form)
        {
            view = form;

            InitializeTaskProcessor();

            view.StartStopClicked += StartOrStop;
            view.FormClosing += OnExit;
        }

        private void OnExit(object sender, FormClosingEventArgs e)
        {
            StopCalculating();

            try
            {
                settings.Save("settings.xml");
            }
            catch
            {
            }
            taskProcessor.Dispose();
            Process.GetCurrentProcess().Kill();
        }

        private void StartOrStop()
        {
            if (!view.backgroundCalculator.IsBusy)
            {
                StartCalculating();
            }
            else
            {
                StopCalculating();
            }
        }

        private void StartCalculating()
        {
            if (Connect())
            {
                view.SetStatusLabel("Идут вычисления");

                view.SetButtonImage(ButtonImage.Stop);
                view.SetButtonText("Остановить вычисления");
                
                view.backgroundCalculator.RunWorkerAsync();
            }
        }

        private void StopCalculating()
        {
            view.SetStatusLabel("Вычисления останавливаются ...");

            view.StopCalculatingForm.SafeShow();

            view.SetButtonImage(ButtonImage.Start);
            view.SetButtonText("Начать вычисления");

            view.backgroundCalculator.CancelAsync();
        }

        private bool Connect()
        {
            bool result;

            connectingForm = new ProgressForm { Header = "Подключение", Message = "Подключение к сервису DCS ..." };
            Program.ShowForm(connectingForm);

            try
            {
                dcsService = new DcsService();
                var client = new ComputationalClient
                {
                    Id = settings.Id,
                    AvailableMemory = view.Me.AvailableMemory,
                    CoreCount = view.Me.CoreCount,
                    CpuFrequency = view.Me.CpuFrequency,
                    LastDate = DateTime.Now
                };
                settings.Id = dcsService.RegisterClient(client);

                view.SetConnectionImage(true);
                view.SetConnectionText("Подключен");
                

                result = true;
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
                result = false;
            }

            connectingForm.SafeHide();

            return result;
        }
    }
}
